package common.fattree;

import ap.BDDACLWrapper;
import common.*;


import java.util.*;

public class HostNode extends Node {
    int packetSpace;
    HashMap<String, HashSet<Announcement>> dstCIBend;
    HashMap<String,HashMap<Integer,Vector<Integer>>> dstRes;

    public HostNode(Device d, int index) {
        super(d, index);
        dstCIBend=new HashMap<>();
        dstRes=new HashMap<>();

    }
    public HostNode(Device d, int index,int packetSpace) {
        super(d, index);
        dstCIBend=new HashMap<>();
        dstRes=new HashMap<>();
        this.packetSpace=packetSpace;

    }

    public void run(){
        runDevice();
    }

    public void startCount(){
        if(this.next.size() == 0){
            long t = System.nanoTime();
            d.printf("%s开始发送计数值%s\n 开始时间为：%s\n", this.d.name, packetSpace, t);
            String id = Utility.getRandomString();

            Announcement a = new Announcement(0, packetSpace, Utility.getOneNumVector(1));
            Vector<Announcement> al = new Vector<>();
            al.add(a);
            CIBIO CIBOut = new CIBIO(al, new ArrayList<>());
            CIBOut.dst = d.name;
            CIBOut.packetSpace = packetSpace;
            d.sendCount(prev, index, CIBOut, id);
            d.addRecord(id, index, "*count start", t);
        }

    }

    public void deviceDone(String srcPort, CIBIO ci, String id) {
        showResult(srcPort,ci, id);  //dst
    }


    public void showResult(String srcPort, CIBIO ci, String id) { //只显示predicate count 部分，id不需要
        HashMap<Integer,Vector<Integer>> tb=new HashMap<>(sortResult(ci));

        long end = System.nanoTime();

        d.println("最终源点的计数向量结果：");
        d.println("destination: "+ci.dst);

        dstRes.put(ci.dst,tb);

        if(d.output) Utility.printCount(tb, bdd);
        d.addRecord(id, index, "*count finish", end);
    }


    public HashMap<Integer,Vector<Integer>> sortResult(CIBIO ci){
        HashSet<Announcement> ce=new HashSet<>(dstCIBend.get(ci.dst));
        if(ci.withdraw.size()>0) {
            for(Announcement a:ce)
            {
                if(ci.withdraw.contains(a.id))
                {
                    dstCIBend.get(ci.dst).remove(a);   //删除withdraw部分
                }
            }
        }else
        {
            dstCIBend.put(ci.dst,new HashSet<>()); //初次
        }
        dstCIBend.get(ci.dst).addAll(ci.announcements);

        HashMap<Integer,Vector<Integer>> tb=new HashMap<>();
        Vector<Integer> v=new Vector<>();
        v.add(0);
        for (Announcement i : dstCIBend.get(ci.dst)) {
            if ((!i.count.equals(v)) && i.predicate != BDDACLWrapper.BDDFalse) {
                tb.put(i.predicate, i.count);
            }
        }
        if (tb.size() == 0) {      //发送来的table为 [1]={0}
            tb.put(1, v);
        }

        return tb;
    }

    //Host lec变化，直接打印上次的结果
    public void getChangeToUpdateCIB(List<Change> changeList, String id){
        showResult(id);
    }

    public void showResult(String id) { //trace为源主机所有的最终的trace:ANY 满足向量

        long end = System.nanoTime();
        d.println("最终源点的计数向量结果：");
        for(String dst:dstRes.keySet()) {
            d.println("destination: " +dst);
            if (d.output) Utility.printCount(dstRes.get(dst), bdd);
        }
        d.addRecord(id, index, "*count finish", end);

    }



    @Override
    public String toString() {
        return getNodeName();
    }
}
